package simple3D.utils 
{
	import flash.geom.Orientation3D;
	import flash.geom.Point;
	import flash.geom.Vector3D;
	import simple3D.geom.Matrix3D;
	import simple3D.geom.Plane;
	/**
	 * ...
	 * @author Dmitriy Gaiduk
	 */
	public class MathUtil 
	{
		
		public static function rotate3D(v:Vector3D, angle:Vector3D):Vector3D
		{
			//calculate trigonometry
			var sinx:Number = Math.sin(angle.x);
			var cosx:Number = Math.cos(angle.x);
			var siny:Number = Math.sin(angle.y);
			var cosy:Number = Math.cos(angle.y);
			//rotate around x axis
			var y1:Number = (v.y * cosx) - (v.z * sinx);
			var z1:Number = (v.z * cosx) + (v.y * sinx);
			//rotate around y axis
			var x2:Number = (v.x * cosy) - (z1 * siny);
			var z2:Number = (z1 * cosy) + (v.x * siny);
			
			return new Vector3D(x2, y1, z2);
		}
		
		public static function rotateXYZ(v:Vector3D, angle:Vector3D):Vector3D
		{
			//calculate trigonometry
			var sinx:Number = Math.sin(angle.x);
			var cosx:Number = Math.cos(angle.x);
			var siny:Number = Math.sin(angle.y);
			var cosy:Number = Math.cos(angle.y);
			var sinz:Number = Math.sin(angle.z);
			var cosz:Number = Math.cos(angle.z);
			var p:Vector3D = new Vector3D();
			//rotate around x axis
			var y1:Number = (v.y * cosx) - (v.z * sinx);
			var z1:Number = (v.z * cosx) + (v.y * sinx);
			//rotate around y axis
			var x2:Number = (v.x * cosy) - (z1 * siny);
			var z2:Number = (z1 * cosy) + (v.x * siny);
			//rotate around z axis
			var x3:Number = x2*cosz + y1*sinz;
			var y3:Number = -x2*sinz + y1*cosz;
			
			return new Vector3D(x3, y3, z2);
		}
		
		private function pointsTransform(points:Vector3D, rotations:Vector3D):Point
		{
			var tpoints:Point;
			var sx:Number = Math.sin(rotations.x);
			var cx:Number = Math.cos(rotations.x);
			var sy:Number = Math.sin(rotations.y);
			var cy:Number = Math.cos(rotations.y);
			var sz:Number = Math.sin(rotations.z);
			var cz:Number = Math.cos(rotations.z);
			var x:Number; 
			var y:Number;
			var z:Number;
			var xy:Number; 
			var xz:Number; 
			var yx:Number
			var yz:Number;
			var zy: Number;
			var zx:Number;
			x = points.x;
			y = points.y;
			z = points.z;
			// rotation around x
			xy = cx*y - sx*z;
			xz = sx*y + cx*z;
			// rotation around y
			yz = cy*xz - sy*x;
			yx = sy*xz + cy*x;
			// rotation around z
			zx = cz*yx - sz*xy;
			zy = sz*yx + cz*xy;
			tpoints = new Point(zx,zy);
			return tpoints;
		}
		
		/**
		 * determinant of the second order
		 * @return 
		 */
		public static function det2(a11:Number, a12:Number, a21:Number, a22:Number):Number
		{
			return a11 * a22 - a12 * a21;
		}
		
		/**
		 * determinant of the third order
		 * @return 
		 */
		public static function det3(matrix:Matrix3D):Number
		{
			return matrix.a11 * det2(matrix.a22, matrix.a23, matrix.a32, matrix.a33) - 
					matrix.a12 * det2(matrix.a21, matrix.a23, matrix.a31, matrix.a33) +
					matrix.a13 * det2(matrix.a21, matrix.a22, matrix.a31, matrix.a32);
		}
		
		
		public static function getIntersectPlane(plane1:Plane, plane2:Plane, plane3:Plane):Vector3D
		{
			var intersectPoint:Vector3D = null;
			var matrixA:Matrix3D = new Matrix3D();
			matrixA.pushLine1(plane1.A, plane1.B, plane1.C);
			matrixA.pushLine2(plane2.A, plane2.B, plane2.C);
			matrixA.pushLine3(plane3.A, plane3.B, plane3.C);
			
			var matrixA1:Matrix3D = new Matrix3D();
			matrixA1.pushLine1(plane1.D, plane1.B, plane1.C);
			matrixA1.pushLine2(plane2.D, plane2.B, plane2.C);
			matrixA1.pushLine3(plane3.D, plane3.B, plane3.C);
			
			var matrixA2:Matrix3D = new Matrix3D();
			matrixA2.pushLine1(plane1.A, plane1.D, plane1.C);
			matrixA2.pushLine2(plane2.A, plane2.D, plane2.C);
			matrixA2.pushLine3(plane3.A, plane3.D, plane3.C);
			
			var matrixA3:Matrix3D = new Matrix3D();
			matrixA3.pushLine1(plane1.A, plane1.B, plane1.D);
			matrixA3.pushLine2(plane2.A, plane2.B, plane2.D);
			matrixA3.pushLine3(plane3.A, plane3.B, plane3.D);
			
			var detA:Number = det3(matrixA);
			var detA1:Number = det3(matrixA1);
			var detA2:Number = det3(matrixA2);
			var detA3:Number = det3(matrixA3);
			if (detA==0)
			{
				return null;
			}
			return new Vector3D(detA1 / detA, detA2 / detA, detA3 / detA);
		}
		
		
		
	}

}